/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 map_segment_overlay.h

	$Header: /heroes4/map_segment_overlay.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( MAP_SEGMENT_OVERLAY_H_INCLUDED )
#define MAP_SEGMENT_OVERLAY_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <cassert>
#include <vector>

#include "map_point.h"
#include "map_rect.h"

// --------------------------------------------------------------------------
// t_map_segment_overlay class template
// --------------------------------------------------------------------------

template < typename t_val >
class t_map_segment_overlay
{
private:
	// Types
	typedef std::vector< t_val >	t_data;

public:
	// Types
	typedef typename t_data::value_type			value_type;
	typedef typename t_data::reference			reference;
	typedef typename t_data::const_reference	const_reference;

	// Constructors
	explicit t_map_segment_overlay(
		t_map_rect_2d const &	extent,
		t_val const &			initial_value = t_val() );
	t_map_segment_overlay(
		t_map_point_2d const &	base,
		t_map_point_2d const &	size,
		t_val const &			initial_value = t_val() );

	// Member functions
	t_map_rect_2d const &	get_extent() const;

	// Operators
	reference		operator[]( t_map_point_2d const & point );
	const_reference	operator[]( t_map_point_2d const & point ) const;

private:
	// Types
	typedef typename t_data::size_type	t_data_index;

	// Data members
	t_map_rect_2d	m_extent;
	t_data			m_data;

	// Types
	t_data_index	compute_index( t_map_point_2d point ) const;
};

// --------------------------------------------------------------------------
// t_map_segment_overlay members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_val >
inline t_map_segment_overlay< t_val >::t_map_segment_overlay(
	t_map_rect_2d const &	extent,
	t_val const &			initial_value )
	:	m_extent( extent ),
		m_data( extent.width() * extent.height(), initial_value )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_val >
inline t_map_segment_overlay< t_val >::t_map_segment_overlay(
	t_map_point_2d const &	base,
	t_map_point_2d const &	size,
	t_val const &			initial_value )
	:	m_extent( base, size ),
		m_data( size.row * size.column, initial_value )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_val >
inline
t_map_rect_2d const & t_map_segment_overlay< t_val >::get_extent() const
{
	return m_extent;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_val >
inline
typename t_map_segment_overlay< t_val >::reference
t_map_segment_overlay< t_val >::operator[]( t_map_point_2d const & point )
{
	return m_data[ compute_index( point ) ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_val >
inline
typename t_map_segment_overlay< t_val >::const_reference
t_map_segment_overlay< t_val >::operator[](
	t_map_point_2d const & point ) const
{
	return m_data[ compute_index( point ) ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_val >
inline
typename t_map_segment_overlay< t_val >::t_data_index
t_map_segment_overlay< t_val >::compute_index( t_map_point_2d point ) const
{
	assert( point.row >= m_extent.top_left.row );
	assert( point.column >= m_extent.top_left.column );
	assert( point.row < m_extent.bottom_right.row );
	assert( point.column < m_extent.bottom_right.column );

	point -= m_extent.top_left;
	return point.row * m_extent.width() + point.column;
}

#endif // !defined( MAP_SEGMENT_OVERLAY_H_INCLUDED )
